1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.collect;
18
19 import static com.google.common.truth.Truth.assertThat;
20
21 import com.google.common.annotations.GwtCompatible;
22 import com.google.common.base.Joiner;
23 import com.google.common.collect.ImmutableSortedMap.Builder;
24 import com.google.common.collect.testing.SortedMapInterfaceTest;
25
26 import junit.framework.TestCase;
27
28 import java.io.Serializable;
29 import java.util.Collections;
30 import java.util.Comparator;
31 import java.util.LinkedHashMap;
32 import java.util.Map;
33 import java.util.Map.Entry;
34 import java.util.SortedMap;
35
36
37
38
39
40
41
42
43 @GwtCompatible(emulated = true)
44 public class ImmutableSortedMapTest extends TestCase {
45
46
47 public abstract static class AbstractMapTests<K, V>
48 extends SortedMapInterfaceTest<K, V> {
49 public AbstractMapTests() {
50 super(false, false, false, false, false);
51 }
52
53 @Override protected SortedMap<K, V> makeEmptyMap() {
54 throw new UnsupportedOperationException();
55 }
56
57 private static final Joiner joiner = Joiner.on(", ");
58
59 @Override protected void assertMoreInvariants(Map<K, V> map) {
60
61 for (Entry<K, V> entry : map.entrySet()) {
62 assertEquals(entry.getKey() + "=" + entry.getValue(),
63 entry.toString());
64 }
65
66 assertEquals("{" + joiner.join(map.entrySet()) + "}",
67 map.toString());
68 assertEquals("[" + joiner.join(map.entrySet()) + "]",
69 map.entrySet().toString());
70 assertEquals("[" + joiner.join(map.keySet()) + "]",
71 map.keySet().toString());
72 assertEquals("[" + joiner.join(map.values()) + "]",
73 map.values().toString());
74
75 assertEquals(Sets.newHashSet(map.entrySet()), map.entrySet());
76 assertEquals(Sets.newHashSet(map.keySet()), map.keySet());
77 }
78 }
79
80 public static class MapTests extends AbstractMapTests<String, Integer> {
81 @Override protected SortedMap<String, Integer> makeEmptyMap() {
82 return ImmutableSortedMap.of();
83 }
84
85 @Override protected SortedMap<String, Integer> makePopulatedMap() {
86 return ImmutableSortedMap.of("one", 1, "two", 2, "three", 3);
87 }
88
89 @Override protected String getKeyNotInPopulatedMap() {
90 return "minus one";
91 }
92
93 @Override protected Integer getValueNotInPopulatedMap() {
94 return -1;
95 }
96 }
97
98 public static class SingletonMapTests
99 extends AbstractMapTests<String, Integer> {
100 @Override protected SortedMap<String, Integer> makePopulatedMap() {
101 return ImmutableSortedMap.of("one", 1);
102 }
103
104 @Override protected String getKeyNotInPopulatedMap() {
105 return "minus one";
106 }
107
108 @Override protected Integer getValueNotInPopulatedMap() {
109 return -1;
110 }
111 }
112
113 public static class HeadMapTests extends AbstractMapTests<String, Integer> {
114 @Override protected SortedMap<String, Integer> makePopulatedMap() {
115 return ImmutableSortedMap.of("a", 1, "b", 2, "c", 3, "d", 4, "e", 5)
116 .headMap("d");
117 }
118
119 @Override protected String getKeyNotInPopulatedMap() {
120 return "d";
121 }
122
123 @Override protected Integer getValueNotInPopulatedMap() {
124 return 4;
125 }
126 }
127
128 public static class HeadMapInclusiveTests extends AbstractMapTests<String, Integer> {
129 @Override protected SortedMap<String, Integer> makePopulatedMap() {
130 return ImmutableSortedMap.of("a", 1, "b", 2, "c", 3, "d", 4, "e", 5)
131 .headMap("c", true);
132 }
133
134 @Override protected String getKeyNotInPopulatedMap() {
135 return "d";
136 }
137
138 @Override protected Integer getValueNotInPopulatedMap() {
139 return 4;
140 }
141 }
142
143 public static class TailMapTests extends AbstractMapTests<String, Integer> {
144 @Override protected SortedMap<String, Integer> makePopulatedMap() {
145 return ImmutableSortedMap.of("a", 1, "b", 2, "c", 3, "d", 4, "e", 5)
146 .tailMap("b");
147 }
148
149 @Override protected String getKeyNotInPopulatedMap() {
150 return "a";
151 }
152
153 @Override protected Integer getValueNotInPopulatedMap() {
154 return 1;
155 }
156 }
157
158 public static class TailExclusiveMapTests extends AbstractMapTests<String, Integer> {
159 @Override protected SortedMap<String, Integer> makePopulatedMap() {
160 return ImmutableSortedMap.of("a", 1, "b", 2, "c", 3, "d", 4, "e", 5)
161 .tailMap("a", false);
162 }
163
164 @Override protected String getKeyNotInPopulatedMap() {
165 return "a";
166 }
167
168 @Override protected Integer getValueNotInPopulatedMap() {
169 return 1;
170 }
171 }
172
173 public static class SubMapTests extends AbstractMapTests<String, Integer> {
174 @Override protected SortedMap<String, Integer> makePopulatedMap() {
175 return ImmutableSortedMap.of("a", 1, "b", 2, "c", 3, "d", 4, "e", 5)
176 .subMap("b", "d");
177 }
178
179 @Override protected String getKeyNotInPopulatedMap() {
180 return "a";
181 }
182
183 @Override protected Integer getValueNotInPopulatedMap() {
184 return 4;
185 }
186 }
187
188 public static class CreationTests extends TestCase {
189 public void testEmptyBuilder() {
190 ImmutableSortedMap<String, Integer> map
191 = ImmutableSortedMap.<String, Integer>naturalOrder().build();
192 assertEquals(Collections.<String, Integer>emptyMap(), map);
193 }
194
195 public void testSingletonBuilder() {
196 ImmutableSortedMap<String, Integer> map
197 = ImmutableSortedMap.<String, Integer>naturalOrder()
198 .put("one", 1)
199 .build();
200 assertMapEquals(map, "one", 1);
201 }
202
203 public void testBuilder() {
204 ImmutableSortedMap<String, Integer> map
205 = ImmutableSortedMap.<String, Integer>naturalOrder()
206 .put("one", 1)
207 .put("two", 2)
208 .put("three", 3)
209 .put("four", 4)
210 .put("five", 5)
211 .build();
212 assertMapEquals(map,
213 "five", 5, "four", 4, "one", 1, "three", 3, "two", 2);
214 }
215
216 public void testBuilder_withImmutableEntry() {
217 ImmutableSortedMap<String, Integer> map =
218 ImmutableSortedMap.<String, Integer>naturalOrder()
219 .put(Maps.immutableEntry("one", 1))
220 .build();
221 assertMapEquals(map, "one", 1);
222 }
223
224 public void testBuilder_withImmutableEntryAndNullContents() {
225 Builder<String, Integer> builder =
226 ImmutableSortedMap.naturalOrder();
227 try {
228 builder.put(Maps.immutableEntry("one", (Integer) null));
229 fail();
230 } catch (NullPointerException expected) {
231 }
232 try {
233 builder.put(Maps.immutableEntry((String) null, 1));
234 fail();
235 } catch (NullPointerException expected) {
236 }
237 }
238
239 private static class StringHolder {
240 String string;
241 }
242
243 public void testBuilder_withMutableEntry() {
244 ImmutableSortedMap.Builder<String, Integer> builder =
245 ImmutableSortedMap.naturalOrder();
246 final StringHolder holder = new StringHolder();
247 holder.string = "one";
248 Entry<String, Integer> entry = new AbstractMapEntry<String, Integer>() {
249 @Override public String getKey() {
250 return holder.string;
251 }
252 @Override public Integer getValue() {
253 return 1;
254 }
255 };
256
257 builder.put(entry);
258 holder.string = "two";
259 assertMapEquals(builder.build(), "one", 1);
260 }
261
262 public void testBuilderPutAllWithEmptyMap() {
263 ImmutableSortedMap<String, Integer> map
264 = ImmutableSortedMap.<String, Integer>naturalOrder()
265 .putAll(Collections.<String, Integer>emptyMap())
266 .build();
267 assertEquals(Collections.<String, Integer>emptyMap(), map);
268 }
269
270 public void testBuilderPutAll() {
271 Map<String, Integer> toPut = new LinkedHashMap<String, Integer>();
272 toPut.put("one", 1);
273 toPut.put("two", 2);
274 toPut.put("three", 3);
275 Map<String, Integer> moreToPut = new LinkedHashMap<String, Integer>();
276 moreToPut.put("four", 4);
277 moreToPut.put("five", 5);
278
279 ImmutableSortedMap<String, Integer> map
280 = ImmutableSortedMap.<String, Integer>naturalOrder()
281 .putAll(toPut)
282 .putAll(moreToPut)
283 .build();
284 assertMapEquals(map,
285 "five", 5, "four", 4, "one", 1, "three", 3, "two", 2);
286 }
287
288 public void testBuilderReuse() {
289 Builder<String, Integer> builder = ImmutableSortedMap.naturalOrder();
290 ImmutableSortedMap<String, Integer> mapOne = builder
291 .put("one", 1)
292 .put("two", 2)
293 .build();
294 ImmutableSortedMap<String, Integer> mapTwo = builder
295 .put("three", 3)
296 .put("four", 4)
297 .build();
298
299 assertMapEquals(mapOne, "one", 1, "two", 2);
300 assertMapEquals(mapTwo, "four", 4, "one", 1, "three", 3, "two", 2);
301 }
302
303 public void testBuilderPutNullKey() {
304 Builder<String, Integer> builder = ImmutableSortedMap.naturalOrder();
305 try {
306 builder.put(null, 1);
307 fail();
308 } catch (NullPointerException expected) {
309 }
310 }
311
312 public void testBuilderPutNullValue() {
313 Builder<String, Integer> builder = ImmutableSortedMap.naturalOrder();
314 try {
315 builder.put("one", null);
316 fail();
317 } catch (NullPointerException expected) {
318 }
319 }
320
321 public void testBuilderPutNullKeyViaPutAll() {
322 Builder<String, Integer> builder = ImmutableSortedMap.naturalOrder();
323 try {
324 builder.putAll(Collections.<String, Integer>singletonMap(null, 1));
325 fail();
326 } catch (NullPointerException expected) {
327 }
328 }
329
330 public void testBuilderPutNullValueViaPutAll() {
331 Builder<String, Integer> builder = ImmutableSortedMap.naturalOrder();
332 try {
333 builder.putAll(Collections.<String, Integer>singletonMap("one", null));
334 fail();
335 } catch (NullPointerException expected) {
336 }
337 }
338
339 public void testPuttingTheSameKeyTwiceThrowsOnBuild() {
340 Builder<String, Integer> builder
341 = ImmutableSortedMap.<String, Integer>naturalOrder()
342 .put("one", 1)
343 .put("one", 2);
344
345 try {
346 builder.build();
347 fail();
348 } catch (IllegalArgumentException expected) {
349 }
350 }
351
352 public void testOf() {
353 assertMapEquals(
354 ImmutableSortedMap.of("one", 1),
355 "one", 1);
356 assertMapEquals(
357 ImmutableSortedMap.of("one", 1, "two", 2),
358 "one", 1, "two", 2);
359 assertMapEquals(
360 ImmutableSortedMap.of("one", 1, "two", 2, "three", 3),
361 "one", 1, "three", 3, "two", 2);
362 assertMapEquals(
363 ImmutableSortedMap.of("one", 1, "two", 2, "three", 3, "four", 4),
364 "four", 4, "one", 1, "three", 3, "two", 2);
365 assertMapEquals(
366 ImmutableSortedMap.of(
367 "one", 1, "two", 2, "three", 3, "four", 4, "five", 5),
368 "five", 5, "four", 4, "one", 1, "three", 3, "two", 2);
369 }
370
371 public void testOfNullKey() {
372 Integer n = null;
373 try {
374 ImmutableSortedMap.of(n, 1);
375 fail();
376 } catch (NullPointerException expected) {
377 }
378
379 try {
380 ImmutableSortedMap.of("one", 1, null, 2);
381 fail();
382 } catch (NullPointerException expected) {
383 }
384 }
385
386 public void testOfNullValue() {
387 try {
388 ImmutableSortedMap.of("one", null);
389 fail();
390 } catch (NullPointerException expected) {
391 }
392
393 try {
394 ImmutableSortedMap.of("one", 1, "two", null);
395 fail();
396 } catch (NullPointerException expected) {
397 }
398 }
399
400 public void testOfWithDuplicateKey() {
401 try {
402 ImmutableSortedMap.of("one", 1, "one", 1);
403 fail();
404 } catch (IllegalArgumentException expected) {
405 }
406 }
407
408 public void testCopyOfEmptyMap() {
409 ImmutableSortedMap<String, Integer> copy
410 = ImmutableSortedMap.copyOf(Collections.<String, Integer>emptyMap());
411 assertEquals(Collections.<String, Integer>emptyMap(), copy);
412 assertSame(copy, ImmutableSortedMap.copyOf(copy));
413 assertSame(Ordering.natural(), copy.comparator());
414 }
415
416 public void testCopyOfSingletonMap() {
417 ImmutableSortedMap<String, Integer> copy
418 = ImmutableSortedMap.copyOf(Collections.singletonMap("one", 1));
419 assertMapEquals(copy, "one", 1);
420 assertSame(copy, ImmutableSortedMap.copyOf(copy));
421 assertSame(Ordering.natural(), copy.comparator());
422 }
423
424 public void testCopyOf() {
425 Map<String, Integer> original = new LinkedHashMap<String, Integer>();
426 original.put("one", 1);
427 original.put("two", 2);
428 original.put("three", 3);
429
430 ImmutableSortedMap<String, Integer> copy
431 = ImmutableSortedMap.copyOf(original);
432 assertMapEquals(copy, "one", 1, "three", 3, "two", 2);
433 assertSame(copy, ImmutableSortedMap.copyOf(copy));
434 assertSame(Ordering.natural(), copy.comparator());
435 }
436
437 public void testCopyOfExplicitComparator() {
438 Comparator<String> comparator = Ordering.natural().reverse();
439 Map<String, Integer> original = new LinkedHashMap<String, Integer>();
440 original.put("one", 1);
441 original.put("two", 2);
442 original.put("three", 3);
443
444 ImmutableSortedMap<String, Integer> copy
445 = ImmutableSortedMap.copyOf(original, comparator);
446 assertMapEquals(copy, "two", 2, "three", 3, "one", 1);
447 assertSame(copy, ImmutableSortedMap.copyOf(copy, comparator));
448 assertSame(comparator, copy.comparator());
449 }
450
451 public void testCopyOfImmutableSortedSetDifferentComparator() {
452 Comparator<String> comparator = Ordering.natural().reverse();
453 Map<String, Integer> original
454 = ImmutableSortedMap.of("one", 1, "two", 2, "three", 3);
455 ImmutableSortedMap<String, Integer> copy
456 = ImmutableSortedMap.copyOf(original, comparator);
457 assertMapEquals(copy, "two", 2, "three", 3, "one", 1);
458 assertSame(copy, ImmutableSortedMap.copyOf(copy, comparator));
459 assertSame(comparator, copy.comparator());
460 }
461
462 public void testCopyOfSortedNatural() {
463 SortedMap<String, Integer> original = Maps.newTreeMap();
464 original.put("one", 1);
465 original.put("two", 2);
466 original.put("three", 3);
467
468 ImmutableSortedMap<String, Integer> copy
469 = ImmutableSortedMap.copyOfSorted(original);
470 assertMapEquals(copy, "one", 1, "three", 3, "two", 2);
471 assertSame(copy, ImmutableSortedMap.copyOfSorted(copy));
472 assertSame(Ordering.natural(), copy.comparator());
473 }
474
475 public void testCopyOfSortedExplicit() {
476 Comparator<String> comparator = Ordering.natural().reverse();
477 SortedMap<String, Integer> original = Maps.newTreeMap(comparator);
478 original.put("one", 1);
479 original.put("two", 2);
480 original.put("three", 3);
481
482 ImmutableSortedMap<String, Integer> copy
483 = ImmutableSortedMap.copyOfSorted(original);
484 assertMapEquals(copy, "two", 2, "three", 3, "one", 1);
485 assertSame(copy, ImmutableSortedMap.copyOfSorted(copy));
486 assertSame(comparator, copy.comparator());
487 }
488
489 private static class IntegerDiv10 implements Comparable<IntegerDiv10> {
490 final int value;
491
492 IntegerDiv10(int value) {
493 this.value = value;
494 }
495
496 @Override
497 public int compareTo(IntegerDiv10 o) {
498 return value / 10 - o.value / 10;
499 }
500
501 @Override public String toString() {
502 return Integer.toString(value);
503 }
504 }
505
506 public void testCopyOfDuplicateKey() {
507 Map<IntegerDiv10, String> original = ImmutableMap.of(
508 new IntegerDiv10(3), "three",
509 new IntegerDiv10(20), "twenty",
510 new IntegerDiv10(11), "eleven",
511 new IntegerDiv10(35), "thirty five",
512 new IntegerDiv10(12), "twelve"
513 );
514
515 try {
516 ImmutableSortedMap.copyOf(original);
517 fail("Expected IllegalArgumentException");
518 } catch (IllegalArgumentException expected) {
519 }
520 }
521
522 public void testImmutableMapCopyOfImmutableSortedMap() {
523 IntegerDiv10 three = new IntegerDiv10(3);
524 IntegerDiv10 eleven = new IntegerDiv10(11);
525 IntegerDiv10 twelve = new IntegerDiv10(12);
526 IntegerDiv10 twenty = new IntegerDiv10(20);
527 Map<IntegerDiv10, String> original = ImmutableSortedMap.of(
528 three, "three", eleven, "eleven", twenty, "twenty");
529 Map<IntegerDiv10, String> copy = ImmutableMap.copyOf(original);
530 assertTrue(original.containsKey(twelve));
531 assertFalse(copy.containsKey(twelve));
532 }
533
534 public void testBuilderReverseOrder() {
535 ImmutableSortedMap<String, Integer> map
536 = ImmutableSortedMap.<String, Integer>reverseOrder()
537 .put("one", 1)
538 .put("two", 2)
539 .put("three", 3)
540 .put("four", 4)
541 .put("five", 5)
542 .build();
543 assertMapEquals(map,
544 "two", 2, "three", 3, "one", 1, "four", 4, "five", 5);
545 assertEquals(Ordering.natural().reverse(), map.comparator());
546 }
547
548 public void testBuilderComparator() {
549 Comparator<String> comparator = Ordering.natural().reverse();
550 ImmutableSortedMap<String, Integer> map
551 = new ImmutableSortedMap.Builder<String, Integer>(comparator)
552 .put("one", 1)
553 .put("two", 2)
554 .put("three", 3)
555 .put("four", 4)
556 .put("five", 5)
557 .build();
558 assertMapEquals(map,
559 "two", 2, "three", 3, "one", 1, "four", 4, "five", 5);
560 assertSame(comparator, map.comparator());
561 }
562 }
563
564 public void testNullGet() {
565 ImmutableSortedMap<String, Integer> map = ImmutableSortedMap.of("one", 1);
566 assertNull(map.get(null));
567 }
568
569 private static <K, V> void assertMapEquals(Map<K, V> map,
570 Object... alternatingKeysAndValues) {
571 assertEquals(map.size(), alternatingKeysAndValues.length / 2);
572 int i = 0;
573 for (Entry<K, V> entry : map.entrySet()) {
574 assertEquals(alternatingKeysAndValues[i++], entry.getKey());
575 assertEquals(alternatingKeysAndValues[i++], entry.getValue());
576 }
577 }
578
579 private static class IntHolder implements Serializable {
580 public int value;
581
582 public IntHolder(int value) {
583 this.value = value;
584 }
585
586 @Override public boolean equals(Object o) {
587 return (o instanceof IntHolder) && ((IntHolder) o).value == value;
588 }
589
590 @Override public int hashCode() {
591 return value;
592 }
593
594 private static final long serialVersionUID = 5;
595 }
596
597 public void testMutableValues() {
598 IntHolder holderA = new IntHolder(1);
599 IntHolder holderB = new IntHolder(2);
600 Map<String, IntHolder> map
601 = ImmutableSortedMap.of("a", holderA, "b", holderB);
602 holderA.value = 3;
603 assertTrue(map.entrySet().contains(Maps.immutableEntry("a", new IntHolder(3))));
604 Map<String, Integer> intMap
605 = ImmutableSortedMap.of("a", 3, "b", 2);
606 assertEquals(intMap.hashCode(), map.entrySet().hashCode());
607 assertEquals(intMap.hashCode(), map.hashCode());
608 }
609
610 @SuppressWarnings("unchecked")
611 public void testHeadMapInclusive() {
612 Map<String, Integer> map =
613 ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).headMap("three", true);
614 assertThat(map.entrySet()).has().exactly(
615 Maps.immutableEntry("one", 1),
616 Maps.immutableEntry("three", 3)).inOrder();
617 }
618
619 @SuppressWarnings("unchecked")
620 public void testHeadMapExclusive() {
621 Map<String, Integer> map =
622 ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).headMap("three", false);
623 assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("one", 1)).inOrder();
624 }
625
626 @SuppressWarnings("unchecked")
627 public void testTailMapInclusive() {
628 Map<String, Integer> map =
629 ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).tailMap("three", true);
630 assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("three", 3),
631 Maps.immutableEntry("two", 2)).inOrder();
632 }
633
634 @SuppressWarnings("unchecked")
635 public void testTailMapExclusive() {
636 Map<String, Integer> map =
637 ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).tailMap("three", false);
638 assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("two", 2)).inOrder();
639 }
640
641 @SuppressWarnings("unchecked")
642 public void testSubMapExclusiveExclusive() {
643 Map<String, Integer> map =
644 ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", false, "two", false);
645 assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("three", 3)).inOrder();
646 }
647
648 @SuppressWarnings("unchecked")
649 public void testSubMapInclusiveExclusive() {
650 Map<String, Integer> map =
651 ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", true, "two", false);
652 assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("one", 1),
653 Maps.immutableEntry("three", 3)).inOrder();
654 }
655
656 @SuppressWarnings("unchecked")
657 public void testSubMapExclusiveInclusive() {
658 Map<String, Integer> map =
659 ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", false, "two", true);
660 assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("three", 3),
661 Maps.immutableEntry("two", 2)).inOrder();
662 }
663
664 @SuppressWarnings("unchecked")
665 public void testSubMapInclusiveInclusive() {
666 Map<String, Integer> map =
667 ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", true, "two", true);
668 assertThat(map.entrySet()).has().exactly(Maps.immutableEntry("one", 1),
669 Maps.immutableEntry("three", 3), Maps.immutableEntry("two", 2)).inOrder();
670 }
671
672 private static class SelfComparableExample implements Comparable<SelfComparableExample> {
673 @Override
674 public int compareTo(SelfComparableExample o) {
675 return 0;
676 }
677 }
678
679 public void testBuilderGenerics_SelfComparable() {
680 ImmutableSortedMap.Builder<SelfComparableExample, Object> natural =
681 ImmutableSortedMap.naturalOrder();
682
683 ImmutableSortedMap.Builder<SelfComparableExample, Object> reverse =
684 ImmutableSortedMap.reverseOrder();
685 }
686
687 private static class SuperComparableExample extends SelfComparableExample {}
688
689 public void testBuilderGenerics_SuperComparable() {
690 ImmutableSortedMap.Builder<SuperComparableExample, Object> natural =
691 ImmutableSortedMap.naturalOrder();
692
693 ImmutableSortedMap.Builder<SuperComparableExample, Object> reverse =
694 ImmutableSortedMap.reverseOrder();
695 }
696 }
697